<template>
  <div class="myUpload">
    <!--list-type="picture-card"-->
    <!-- -card-->
    <el-upload
      :action="action"
      :auto-upload="autoUpload"
      :before-remove="handleBeforeRemove || defaultBeforeRemove"
      :before-upload="handleBeforeUpload || defaultBeforeUpload"
      :class="{disabled:childModel.length >= limit,hide:hide,'avatar-upload':listType==='picture'}"
      :data="data"
      :disabled="disabled"
      :drag="drag"
      :fileList="childModel"
      :headers="headers"
      :http-request="httpRequest"
      :limit="limit"
      :list-type="listType"
      :multiple="multiple"
      :name="name"
      :on-change="handleChange || defaultChange"
      :on-error="handleError || defaultError"
      :on-exceed="handleExceed || defaultExceed"
      :on-preview="handlePreview || defaultPreview"
      :on-progress="handleProgress || defaultProgress"
      :on-remove="handleRemove || defaultRemove"
      :on-success="handleSuccess || defaultSuccess"
      :show-file-list="showFileList"
      :with-credentials="withCredentials"
      ref="upload"
    >
      <el-button size="small" type="primary" v-if="listType === 'text'">点击上传</el-button>
      <img
        :src="dialogImageUrl"
        class="avatar"
        v-else-if="listType==='picture' && dialogImageUrl && childModel.length>0"/>
      <i class="el-icon-plus picture-icon-plus" v-else></i>
      <div @click.stop="emptyFun" class="el-upload-list--picture-card"
           v-if="listType==='picture' && dialogImageUrl&& childModel.length>0">
        <div class=" el-upload-list__item-actions">
          <span @click="defaultPreview" class="el-upload-list__item-preview"><i class="el-icon-zoom-in"></i></span>
          <span @click="pictureRemove"
                class="el-upload-list__item-delete"
                v-if="status.del">
            <i class="el-icon-delete"></i>
          </span>
        </div>
      </div>
    </el-upload>
    <el-dialog :title="dialogImageName" :visible.sync="dialogVisible" append-to-body class="upload_dialog" top="0"
               width="60%">
      <img :src="dialogImageUrl" alt="" width="100%">
    </el-dialog>
  </div>
</template>

<script>

export default {
  name: 'myUpload',
  props: {
    // 组件当前绑定值 [{url:'xxxxxx.com',name:'示例图片1'}]
    model: {
      type: Array,
      require: true
    },
    // 提交响应地址
    action: {
      type: String,
      default () {
        return ''
      }
    },
    // 绑定值的字段别名 url为文件地址 name为文件名称
    props: {
      type: Object,
      default () {
        return {url: 'url', name: 'name'}
      }
    },
    // 文件大小限制，单位为MB
    fileSize: {
      type: Number,
      default () {
        return 2
      }
    },
    // 文件类型限制
    // 常用 image/gif，image/jpeg，application/pdf，image/png，text/plain
    fileType: {
      type: Array,
      default () {
        return ['image/jpeg', 'application/pdf', 'image/png']
      }
    },
    // 设置请求头部
    headers: {
      type: Object,
      default () {
        return {}
      }
    },
    // 上传的文件字段名
    name: {
      type: String,
      default () {
        return 'files'
      }
    },
    // 上传时附带的额外参数
    data: {
      type: Object,
      default () {
        return {}
      }
    },
    // 覆盖默认上传方法
    httpRequest: {
      type: Function
    },
    // 是否支持多选文件
    multiple: {
      type: Boolean,
      default () {
        return false
      }
    },
    // 当前文件列表类型 text/picture/picture-card
    listType: {
      type: String,
      default () {
        return 'picture-card'
      }
    },
    // 当前文件类型为picture时判断图片上按钮显示状态 del删除按钮
    status: {
      type: Object,
      default () {
        return {}
      }
    },
    // 是否启用拖拽
    drag: {
      type: Boolean,
      default () {
        return false
      }
    },
    // 最大允许上传个数
    limit: {
      type: Number,
      default () {
        return 1
      }
    },
    // 选取后自动上传
    autoUpload: {
      type: Boolean,
      default () {
        return false
      }
    },
    // 是否显示已上传文件列表
    showFileList: {
      type: Boolean,
      default () {
        return true
      }
    },
    // 支持发送 cookie 凭证信息
    withCredentials: {
      type: Boolean,
      default () {
        return false
      }
    },
    // 点击文件列表中已上传的文件时的钩子
    handlePreview: {
      type: Function
    },
    // 文件列表移除文件时的钩子
    handleRemove: {
      type: Function
    },
    // 文件上传成功时的钩子
    handleSuccess: {
      type: Function
    },
    // 文件上传失败时的钩子
    handleError: {
      type: Function
    },
    // 文件上传时的钩子
    handleProgress: {
      type: Function
    },
    // 文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用
    handleChange: {
      type: Function
    },
    // 上传文件之前的钩子，参数为上传的文件，若返回 false 或者返回 Promise 且被 reject，则停止上传
    handleBeforeUpload: {
      type: Function
    },
    // 删除文件之前的钩子，参数为上传的文件和文件列表，若返回 false 或者返回 Promise 且被 reject，则停止删除
    handleBeforeRemove: {
      type: Function
    },
    // 文件超出个数限制时的钩子
    handleExceed: {
      type: Function
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default () {
        return false
      }
    }
  },
  data () {
    return {
      dialogImageName: '',
      dialogImageUrl: '',
      dialogVisible: false,
      childModel: this.model,
      hide: false
    }
  },
  computed: {},
  watch: {
    childModel (val) {
      this.$emit('update:model', val)
    },
    model (val) {
      if (val !== this.childModel) {
        this.childModel = val
      }
    }
  },
  created () {
  },
  updated () {
    if (this.listType === 'picture' && Array.isArray(this.childModel) && this.childModel.length > 0) {
      this.dialogImageUrl = this.childModel[0][this.props.url]
      this.dialogImageName = this.childModel[0][this.props.name]
    }
  },
  methods: {
    pictureRemove () {
      //        this.$confirm(`确定移除 ${ file.name }？`, '删除', {type: 'warning'}).then(function () {
      //        });
      this.childModel = []
      this.dialogImageUrl = ''
      this.dialogImageName = ''
    },
    defaultPreview (file) {
      this.dialogImageUrl = file[this.props.url]
      this.dialogImageName = file[this.props.name]
      //        this.dialogImageUrl = URL.createObjectURL(file.raw);
      this.dialogVisible = true
    },
    defaultRemove (file, fileList) {
      this.childModel = fileList
    },
    // 上传成功
    defaultSuccess (response, file, fileList) {
    },
    // 上传失败
    defaultError (err, file, fileList) {
      throw err
    },
    // 文件上传时，用于进度监听
    defaultProgress (event, file, fileList) {
    },
    // 监听文件状态改变
    defaultChange (file, fileList) {
      // 文件类型
      const fileType = file.raw.type
      // 文件大小
      const fileSize = file.raw.size / 1024 / 1024
      // 判断文件类型以及大小
      let typeFlag = false
      let sizeFlag = false
      for (let item of this.fileType) {
        if (item === fileType) {
          typeFlag = true
        }
      }
      if (fileSize < this.fileSize) {
        sizeFlag = true
      }

      if (!typeFlag) {
        this.$message.error(`上传文件类型只能是 ${this.fileType.join(',')}格式!`)
      } else if (!sizeFlag) {
        this.$message.error(`上传文件大小不能超过 ${this.fileSize}MB!`)
      }

      if (typeFlag && sizeFlag) {
        this.childModel = fileList
        //          this.dialogImageUrl = URL.createObjectURL(file.raw);
        this.dialogImageUrl = file[this.props.url]
        this.dialogImageName = file[this.props.name]
      } else {
        // 当上传不通过的时候去除fileList最后一项
        fileList.splice(fileList.length - 1, 1)
      }
    },
    // 监听上传文件之前状态
    defaultBeforeUpload (file) {
    },
    // 监听移除文件之前状态
    defaultBeforeRemove (file, fileList) {
      const _this = this
      return this.$confirm(`确定移除 ${file.name}？`, '删除', {type: 'warning'}).then(function () {
        if (_this.limit === 1) {
          _this.hide = true
          setTimeout(() => {
            _this.hide = false
          }, 520)
        }
      })
    },
    // 监听文件超出个数限制
    defaultExceed (files, fileList) {
      this.$message.warning(`当前限制选择 ${this.limit} 个文件`)
    },
    emptyFun () {

    }
  }

}
</script>

<style lang="scss">
  .myUpload {
    .avatar-upload {
      .el-upload-list--picture-card .el-upload-list__item-actions span + span {
        margin-left: 10px;
      }

      .el-upload {
        border: 1px dashed #d9d9d9;
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
      }

      .el-upload:hover {
        border-color: #409EFF;
      }

      .picture-icon-plus {
        font-size: 28px;
        color: #8c939d;
        text-align: center;
      }

      .avatar {
        width: 100%;
        height: 100%;
        display: block;
      }
    }

    .hide .el-upload--picture-card {
      opacity: 0;
    }

    .show .el-upload--picture-card {
      opacity: 0;
      transition: opacity 1s;
    }

    .disabled .el-upload--picture-card {
      display: none;
    }
  }

</style>
